--File ： ChapterView.lua
--Author : zee
--Date   : 2015/4/8
--Description : 主界面，从scene来，用于组织所有的layer，层级等等。




PlayLayer = class("PlayLayer",function()
    -- 继承
    local ret = cc.Layer:create()

    ret.start = nil
    ret.canTouch = true
    ret.isGameEnd = false
    return ret
end)

PlayLayer.__index = PlayLayer


function PlayLayer:create()
    local ret = PlayLayer:new()
    return ret
end




--------------------------------------------------------
-- 初始化
--------------------------------------------------------
function PlayLayer:start()
    -- 
    local layer = cc.LayerColor:create()
    layer:setColor( cc.c3b(0,0,0) )
    layer:setOpacity( 255 )
    self:addChild( layer )

    self:makeUI()
    self:makeData()
    self:uiRest()
    self:gameStart()

    -- 添加逐帧方法:
    local function frameEvent(dt) 
        self:onFrame(dt) 
    end
    self:scheduleUpdateWithPriorityLua( frameEvent, 0 )
end




function PlayLayer:makeUI()
    self.rootNode = cc.CSLoader:createNode("csb/play/play.csb")
    self:addChild( self.rootNode )

    self.score = SearchChildByName( self.rootNode, "score" )
    self.fnt_1 = SearchChildByName( self.rootNode, "fnt_1" )
    self.fnt_2 = SearchChildByName( self.rootNode, "fnt_2" )
    self.fnt_res_0 = SearchChildByName( self.rootNode, "fnt_res_0" )
    self.fnt_res_1 = SearchChildByName( self.rootNode, "fnt_res_1" )
    self.use_show = SearchChildByName( self.rootNode, "use_show" )
    self.btn_how = SearchChildByName( self.rootNode, "btn_how" )
    self.btn_back = SearchChildByName( self.rootNode, "back" )

    self.img_tips = SearchChildByName( self.rootNode, "img_tips")
    self.text_tips = SearchChildByName( self.rootNode, "text_tips")
    self.tips_left = SearchChildByName( self.rootNode, "tips_left")
    self.tips_right = SearchChildByName( self.rootNode, "tips_right")

    self.ary_cub_left = {}
    self.ary_cub_right = {}
    local main_left = SearchChildByName( self.rootNode, "main_left" )
    local main_right = SearchChildByName( self.rootNode, "main_right" )
    main_left:setOpacity(110)
    main_right:setOpacity(110)
    for i=1,4 do
        -- left
        for j=1,2 do 
            local idx = (i-1)*2+j
            local nod = SearchChildByName( main_left, "c_"..idx )
            local cub = PlayCub:create()
            cub:bind( nod )
            cub:setIsLeft( true )
            local function clickEvt()
                self:onCLickCub(cub)
            end
            local function TouchOnEvent(node, touch) 
                self:onTouchOn(cub)
            end
            local function cancelEvent(node, touch) 
                self:onTouchCancel(cub)
            end

            AddTouchEvent( cub.btn,  clickEvt, UI:getInstance(),  TouchOnEvent, nil, cancelEvent )
            --
            self.ary_cub_left[ idx ] = cub
            cub:setLinePos( j ,i ,idx )
        end
        -- right
        for j=1,2 do 
            local idx = (i-1)*2+j
            local nod = SearchChildByName( main_right, "c_"..idx )
            local cub = PlayCub:create()
            cub:bind( nod )
            cub:setIsLeft( false )
            local function clickEvt()
                self:onCLickCub(cub)
            end
            local function TouchOnEvent(node, touch) 
                self:onTouchOn(cub)
            end
            local function cancelEvent(node, touch) 
                self:onTouchCancel(cub)
            end

            AddTouchEvent( cub.btn,  clickEvt, UI:getInstance(),  TouchOnEvent, nil, cancelEvent )
            --
            self.ary_cub_right[ idx ] = cub
            cub:setLinePos( j ,i ,idx )
        end
    end

    self.score:setString("0")
    self.fnt_1:setVisible(false)
    self.fnt_2:setVisible(false)
    self.fnt_res_0:setVisible(false)
    self.fnt_res_1:setVisible(false)

    local function evt( )
        Sound(9)
        local score = PlayGameData:getInstance().score
        local step = PlayGameData:getInstance().step
        PlayRankData:getInstance():gameEndToRank( score, step )
        UI:getInstance():popLastView()
    end
    AddTouchEvent( self.btn_back,  evt, self)
    self.btn_back:setOpacity( 0 )

    local function evt_how( )
        Sound(9)
        local how = PlayRuleNode:create()
        self:addChild(how)
        how:start()
    end
    self.btn_how:setOpacity( 0 )
    AddTouchEvent( self.btn_how,  evt_how, self)
end




function PlayLayer:makeData()
    PlayGameData:getInstance():testInit()
end




function PlayLayer:updateUI()
    local gameData = PlayGameData:getInstance()
    -- 
    self.score:setString( "" .. gameData.score )
    -- 
    self.fnt_1:setString( ""..(gameData.firstNum or 0) )
    self.fnt_1:setVisible( gameData.firstNum~=nil )
    -- 
    self.fnt_2:setString( ""..(gameData.lastNum or 0) )
    self.fnt_2:setVisible( gameData.lastNum~=nil )
    -- 
    local testRes = (gameData.firstNum or 0) + (gameData.lastNum or 0)
    local testGe = testRes%10
    local testShi = (testRes-(testRes%10))/10
    self.fnt_res_0:setString( ""..testShi )
    self.fnt_res_0:setVisible( testShi~=0 )
    self.fnt_res_1:setString( ""..testGe )
    self.fnt_res_1:setVisible( (gameData.firstNum~=nil) and (gameData.lastNum~=nil) )
    -- 随时检查是不是有满格的了。
    self:warnFullZero()
end




function PlayLayer:onFrame(dt)
    if( self.timeCount==nil ) then 
        self.timeCount = 0
    end
    -- 每过几帧就执行
    local timeRound = 1
    self.timeCount = self.timeCount + 1
    if( self.timeCount>=timeRound ) then
        self.timeCount = 0
        -- 更新界面
        self:updateUI()
        -- 更新警告或提示检查状态。
        self:updateWarningText()

        -- 如果游戏结束了，就不再执行
        if( self.isGameEnd==true )then 
            return
        end

        -- 检查是否结束
        if self:checkIsEnd()==true then 
            cclog("要结束了")
            self:gameWillEnd()
            self.isGameEnd = true
        end
    end
end





-- ***************************************************************************
-- Tools
-- ***************************************************************************
-- 寻找一个空闲的cub
function PlayLayer:findBlankAndCount( ary )
    local resCub = {}
    local resCount = 0
    for i=1,8 do
        local cub = ary[i]
        if( cub:getNum()==nil )then
            resCount = resCount + 1
            resCub[ resCount ] = cub
        end
    end
    ----
    if( resCount==0 ) then
        return nil, 0
    else
        local cub = resCub[ math.random(1,resCount) ]
        return cub, resCount
    end
end





function PlayLayer:showNextNum( ary , num  )
    local cub,_c = self:findBlankAndCount(ary)        
    if (cub) then 
        local settingNum = num or self:getNextOutNum()
        -- cclook("展示下一个: (%s-%s) , num=%s", cub.line_x, cub.line_y, settingNum )
        cub:setNum( settingNum )
    else
        cclook(" 已经没有剩余的格子可以显示了。 ")
    end
end




-- 随机出下一个要出现的 num
function PlayLayer:getNextOutNum()
    local gameData = PlayGameData:getInstance()
    local max = getTableCount( gameData.birthNumTab )  
    -- cclook(" 当钱使用的 随机数池子 : %s", gameData.birthNumTab )
    return gameData.birthNumTab[ math.random( 1, max ) ]
end




-- 检查游戏是否结束
function PlayLayer:checkIsEnd()
    -- 只要有一个区域的牌子已经达成了8个0记录，就不会结束。
    if( self:checkOneAryFull(self.ary_cub_left)==true ) then
        return false
    elseif ( self:checkOneAryFull( self.ary_cub_right )==true ) then
        return false
    end
    -- 任意一个 cub 的值为0或者nil，则还能继续。
    local leftEnd = self:getBlanksNum( self.ary_cub_left )==0
    local rightEnd = self:getBlanksNum( self.ary_cub_right )==0
    -- 只要有一个区域的数字满了，就游戏结束。不应该等待下一步是否能合成这个条件，否则可以作弊。
    if( leftEnd==true )then
        return true
    elseif( rightEnd==true )then
        return true
    end
    return false
end


-- 判断是不是某个区域到了濒危状态（空闲格子少于2个）
function PlayLayer:updateWarningText(  )
    if(self:checkOneAryFull(self.ary_cub_left)==true) then 
        self.text_tips:setString("左边的可以消除了");
        self.img_tips:setVisible( true )
        self.tips_left:setVisible(true)
        self.tips_right:setVisible( false )

    elseif (self:checkOneAryFull(self.ary_cub_right)==true) then 
        self.text_tips:setString("右边的可以消除了");
        self.img_tips:setVisible( true )
        self.tips_left:setVisible(false)
        self.tips_right:setVisible( true )
        cclog("   can right")

    elseif (self:getBlanksNum( self.ary_cub_left )==1 ) then 
        self.text_tips:setString("左边的只剩最后一个可生各自啦");
        self.img_tips:setVisible( true )
        self.tips_left:setVisible(true)
        self.tips_right:setVisible( false )

    elseif (self:getBlanksNum( self.ary_cub_right )==1 ) then
        self.text_tips:setString("右边的只剩最后一个可生格子啦");
        self.img_tips:setVisible( true )
        self.tips_left:setVisible(false)
        self.tips_right:setVisible( true )

    elseif ( self.isGameEnd==false) then 
        self.img_tips:setVisible(false)

    elseif( self.isGameEnd==true) then
        self.text_tips:setString("没有可再生的格子了，游戏即将结束...");
        self.img_tips:setVisible( true )
        self.tips_left:setVisible(false)
        self.tips_right:setVisible( false )
    end 
end


-- 获取一个区域的空闲cub的数量
function PlayLayer:getBlanksNum( ary )
    local blanks = 0
    for i,cub in pairs( ary ) do 
        local check_1 = nil
        local check_2 = 0  
        if( cub:getNum()==check_1 or cub:getNum()==check_2 )then 
            blanks = blanks + 1
        end
    end
    return blanks
end



function PlayLayer:checkOneAryFull( ary )
    local full = 0
    for i,cub in pairs( ary ) do 
        if( cub:isHaveZero()==true )then 
            full = full + 1
        end
    end
    return full>=8
end



-- 检查左边或右边的全部都有zero了，全部的。
function PlayLayer:findZeroLine( cub )
    local ary = nil
    if self:checkOneAryFull( self.ary_cub_left ) and cub:getIsLeft()==true then 
        ary = self.ary_cub_left
    elseif self:checkOneAryFull( self.ary_cub_right ) and cub:getIsLeft()==false then 
        ary = self.ary_cub_right
    else
        return false
    end
    ---- 
    if( ary ) then 
        cclog(" :%s", "开始了  开始计算喷喷")
        self.canTouch = false
        local gameData = PlayGameData:getInstance()
        local evtTab = {}
        for i=1,8 do 
            local one = ary[i]
            local function setOneZero()
                gameData:addOneZero()
                one:setNum( nil )
                one:setHaveZero( false )
                Sound(10)
            end
            table.insert( evtTab, setOneZero )
        end
        --
        local function setOneLine()
            gameData:addOneLineZero(8)
            self:updateUI()
            self:onOneStep( ary==self.ary_cub_left, ary==self.ary_cub_right)
            self.canTouch = true
        end
        table.insert( evtTab, setOneLine )
        -- 连续动作：消除单边所有的东西，并且
        FuncOneByOne( 0.1, evtTab, self )
        return true
    end
    return false
end




function PlayLayer:warnFullZero()
    if( self:checkOneAryFull(self.ary_cub_left)==true )then 
        for i,cub in pairs( self.ary_cub_left ) do 
            cub:setShanShuo(true)
        end
    end
    if( self:checkOneAryFull(self.ary_cub_right)==true )then 
        for i,cub in pairs( self.ary_cub_right ) do 
            cub:setShanShuo(true)
        end
    end
end



function PlayLayer:checkCanTouch( cub )
    if( self.canTouch==false ) then 
        return false
    end
    --
    if( self.lastCub~=nil ) then -- 第二个都已经出现了，就一定不能再触摸
        return false 
    elseif( self.firstCub==nil ) then -- 第一个没有，一定可以选中
        return true
    elseif( self.firstCub:getIsLeft()==cub:getIsLeft() ) then -- 选第二个的时候，如果同边，就不能触摸
        return false
    else
    end
    return true
end






-- *************************************************************************** --
--      Run
-- *************************************************************************** --
function PlayLayer:uiRest()
    -- 界面数据归0，一切初始化。
    for i=1 ,8 do 
        self.ary_cub_left[i]:setNum(nil)
        self.ary_cub_right[i]:setNum(nil)
    end
end



function PlayLayer:gameStart()
    local gameData = PlayGameData:getInstance()
    gameData.step = 1
    gameData.score = 0
        
    self:showNextNum( self.ary_cub_left, nil )
    self:showNextNum( self.ary_cub_right, nil )
    self:showNextNum( self.ary_cub_left, nil )
    self:showNextNum( self.ary_cub_right, nil )
end


function PlayLayer:gameWillEnd()
    cclog("游戏马上要结束了")
    local dey = cc.DelayTime:create(2)
    local function cb()
        self:gameEnd()
    end
    local cal = cc.CallFunc:create(cb)
    local seq = cc.Sequence:create( dey, cal )
    self:runAction(seq)
end


function PlayLayer:gameEnd()
    self.canTouch = false
    cclook(" 游戏结束 ")
    local endLay = PlayEndNode:create()
    self:addChild(endLay)
    endLay:start()
    local function evtee()
        UI:getInstance():popLastView()
    end
    endLay:setClickEvt(evtee)
    -- 
    local gameData = PlayGameData:getInstance()
    local score = PlayGameData:getInstance().score
    local step = PlayGameData:getInstance().step
    PlayRankData:getInstance():gameEndToRank( score, step )
    -- 获取本次的名次。
    local st = PlayRankData:getInstance():getRankByScore()
    cclook(" 本次名次 :%s", st )
    -- 
    endLay:setGameEndInfo( true, gameData.score )
end



function PlayLayer:onOneStep(bLeft, bRight)
    -- 新的数字出生要有一定的延时。
    local function bank() end
    local function birthEvt()
        local once = 1
        for i=1,once do 
            if(bLeft)then 
                self:showNextNum( self.ary_cub_left, nil )
            end
            if(bRight) then 
                self:showNextNum( self.ary_cub_right, nil )
            end
        end
    end
    FuncOneByOne(0.5, { bank, birthEvt} , self)
    
    -- 增加步数
    local gameData = PlayGameData:getInstance()
    gameData.firstNum = nil
    gameData.lastNum = nil
    gameData.step = gameData.step + 1
    -- 恢复
    self.firstCub = nil
    self.lastCub = nil
end



-- 触摸结束，判断。
function PlayLayer:onCLickCub(cub)
    --
    if( cub:getNum()==0 )then 
        return
    end
    --
    if( self.firstCub~=nil and self.lastCub~=nil and 
        ( self.firstCub==cub or self.lastCub==cub ) ) then
        local gameData = PlayGameData:getInstance()
        if ( (gameData.firstNum+gameData.lastNum)%10==0 ) then
            -- gameData:addOneZero()
            gameData:addOne()
            self.firstCub:setNum( 0 )
            self.lastCub:setNum ( nil )
            local function zeroEvt()
                gameData:addOneZero()
                Sound(10)
                self:updateUI()
            end
            self.firstCub:setZeroFunc(zeroEvt)
        else 
            self.firstCub:setNum( (gameData.firstNum+gameData.lastNum)%10 )
            gameData:addOne()
            self.lastCub:setNum ( nil )
        end
        self:onOneStep(true,true)
        self:updateUI()

        Sound(2)
    end
    self:onTouchCancel(cub)
end



-- 触摸到
function PlayLayer:onTouchOn(cub)
    -- 一点触摸就要判断单行的结算
    if( self:findZeroLine(cub)==true ) then  
        return
    end
    -- 触摸到0，直接清算。
    if( cub:getNum()==0 )then 
        return
    end
    -- 触摸到同行。
    if( self:checkCanTouch(cub)==false ) then
        self:updateUI()
        return
    end
    -- 触摸到，标记
    if( cub:getNum()~=nil ) then
        local gameData = PlayGameData:getInstance()
        if ( gameData.firstNum==nil ) then
            gameData.firstNum = cub:getNum()
            self.firstCub = cub
        elseif (gameData.lastNum==nil ) then 
            gameData.lastNum = cub:getNum()
            self.lastCub = cub
        end
        Sound(3)
    end
    -- update
    self:updateUI()
end



-- 触摸取消
function PlayLayer:onTouchCancel(cub)
    local gameData = PlayGameData:getInstance()
    if( cub==self.firstCub ) then
        self.firstCub = nil
        gameData.firstNum = nil
    elseif (cub==self.lastCub ) then
        self.lastCub = nil
        gameData.lastNum = nil
    end
    self:updateUI()
end






















